﻿@page "/Account/Manage/Email"

@using System.ComponentModel.DataAnnotations
@using System.Text
@using System.Text.Encodings.Web
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.WebUtilities
@using MyApp.Data

@inject UserManager<ApplicationUser> UserManager
@inject IEmailSender<ApplicationUser> EmailSender
@inject IdentityUserAccessor UserAccessor
@inject NavigationManager NavigationManager

<PageTitle>Manage email</PageTitle>

<Heading3>Manage email</Heading3>

<div class="max-w-xl">
    <StatusMessage Message="@message" />

    <div class="mt-3 shadow overflow-hidden sm:rounded-md">
        <div class="px-4 bg-white dark:bg-black sm:p-6">
            <form id="send-verification-form" @onsubmit="OnSendEmailVerificationAsync" @formname="send-verification" method="post">
                <AntiforgeryToken />
            </form>
            <EditForm id="change-email-form" Model="Input" FormName="change-email" OnValidSubmit="OnValidSubmitAsync" method="post">
                <DataAnnotationsValidator />
                <ValidationSummary class="mb-3 text-danger text-center font-semibold" />

                <div class="flex flex-col gap-4">
                    @if (isEmailConfirmed)
                    {
                        <div>
                            <label for="email" class="@TextInput.LabelClasses">Email</label>
                            <div class="mt-1 relative rounded-md shadow-sm">
                                <input id="email" type="text" value="@email" class="@TextInput.InputClasses" placeholder="Please enter your email." disabled />
                            </div>
                        </div>
                    }
                    else
                    {
                        <div>
                            <label for="email" class="@TextInput.LabelClasses">Email</label>
                            <div class="mt-1 relative rounded-md shadow-sm">
                                <input id="email" type="text" value="@email" class="@TextInput.InputClasses" placeholder="Please enter your email." disabled />
                            </div>
                            <SecondaryButton id="email-verification" type="submit" form="send-verification-form">Send verification email</SecondaryButton>
                        </div>
                    }
                <div>
                    <label for="new-email" class="@TextInput.LabelClasses">New email</label>
                    <div class="mt-1 relative rounded-md shadow-sm">
                        <InputText id="new-email" type="text" @bind-Value="Input.NewEmail" class="@TextInput.InputClasses" autocomplete="email" aria-required="true" placeholder="Please enter new email." />
                    </div>
                    <ValidationMessage For="() => Input.NewEmail" class="mt-2 text-danger text-sm" />
                </div>
                <div>
                    <PrimaryButton id="change-email-button" type="submit">Change email</PrimaryButton>
                </div>
            </div>
            </EditForm>
        </div>
    </div>
</div>

@code {
    private string? message;
    private ApplicationUser user = default!;
    private string? email;
    private bool isEmailConfirmed;

    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    [SupplyParameterFromForm(FormName = "change-email")]
    private InputModel Input { get; set; } = new();

    protected override async Task OnInitializedAsync()
    {
        user = await UserAccessor.GetRequiredUserAsync(HttpContext);
        email = await UserManager.GetEmailAsync(user);
        isEmailConfirmed = await UserManager.IsEmailConfirmedAsync(user);

        Input.NewEmail ??= email;
    }

    private async Task OnValidSubmitAsync()
    {
        if (Input.NewEmail is null || Input.NewEmail == email)
        {
            message = "Your email is unchanged.";
            return;
        }

        var userId = await UserManager.GetUserIdAsync(user);
        var code = await UserManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail);
        code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
        var callbackUrl = NavigationManager.GetUriWithQueryParameters(
            NavigationManager.ToAbsoluteUri("Account/ConfirmEmailChange").AbsoluteUri,
            new Dictionary<string, object?> { ["userId"] = userId, ["email"] = Input.NewEmail, ["code"] = code });

        await EmailSender.SendConfirmationLinkAsync(user, Input.NewEmail, HtmlEncoder.Default.Encode(callbackUrl));

        message = "Confirmation link to change email sent. Please check your email.";
    }

    private async Task OnSendEmailVerificationAsync()
    {
        if (email is null)
        {
            return;
        }

        var userId = await UserManager.GetUserIdAsync(user);
        var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
        code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
        var callbackUrl = NavigationManager.GetUriWithQueryParameters(
            NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
            new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code });

        await EmailSender.SendConfirmationLinkAsync(user, email, HtmlEncoder.Default.Encode(callbackUrl));

        message = "Verification email sent. Please check your email.";
    }

    private sealed class InputModel
    {
        [Required]
        [EmailAddress]
        [Display(Name = "New email")]
        public string? NewEmail { get; set; }
    }
}
